/*
 * Utils.h
 *
 *  Created on: 27/09/2011
 *      Author: Pablo Arias
 */

#ifndef UTILS_H_
#define UTILS_H_
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "bootsector.h"
#include "lista.h"

		// potencia2: hace una potencia con base 2 elevado a la n.
		unsigned int potencia2(char n){
			unsigned int resultado = 1;
			int i;
			for(i = 1; i <= n; i++){
				resultado = resultado * 2;
			}
			return resultado;
		}

		// byteToBin: Pasa un byte a binario.
 char *byteToBin(char n){
				int i;
				static char ret[8];

				for(i=0; i < 8; i++)
				{
					if((n & potencia2(7 - i)) == potencia2(7 - i))
						ret[i] = '1';

						else
						ret[i] = '0';
				}
				return ret;
			}

		// binToByte: pasa un byte en binario a decimal, espera como argumento el numero y su longitud EN BITS!
		unsigned int binToByte(char *n,char len)
		{
			unsigned int resultado = 0;
			int i;
			for(i = 0; i < len; i++)
			{
				if( n[i] == '1')
					resultado = resultado + potencia2((len-1) - i);

			}
			/*n = NULL;
			free(n);*/
			return resultado;

		}

		//Pasa un conjunto de bytes a decimal usando Big Endian.. espera el conjunto y su longitud EN BYTES!!!
		unsigned int toBigEndian(char *bytes, char len)
		{
			char *cadena;
			cadena = malloc( len*sizeof(char) );
			*cadena = 0;
			int i;

			for(i=0; i < len; i++)
			{
				strcat(cadena,byteToBin(bytes[i]));
			}

			return binToByte(cadena,8*len);
		}

		//Pasa un conjunto de bytes a decimal usando Little Endian.. espera el conjunto y su longitud EN BYTES!!!
		unsigned int toLilEndian(char bytes[], char len)
				{
					char *cadena;

					cadena = malloc( len*sizeof(char) );
					*cadena = 0;
					int i;

					for(i= len -1; i >= 0; i--)
					{
						strcat(cadena,byteToBin(bytes[i]));
					}


					return binToByte(cadena,8*len);
				}

					unsigned int getFatSize(char *bootSector)
					{
						char aux[4] = {bootSector[0x24],bootSector[0x25],bootSector[0x26],bootSector[0x27]};
						return toLilEndian(aux,4);
					}

					unsigned int getReservedSectors(char *bootSector)
					{
						char aux[2] = {bootSector[0xE],bootSector[0xF]};
						return toLilEndian(aux,2);
					}

					char getSectorPerCluster(char *bootSector)
					{
						char aux[1] = {bootSector[0xD]};
						return toLilEndian(aux,1);
					}

					char getNumberOfFat(char *bootSector)
					{
						char aux[1] = {bootSector[0x10]};
						return toLilEndian(aux,1);
					}

					unsigned int getRootCluster(char *bootSector)
					{
						char aux[4] = {bootSector[0x2C],bootSector[0x2D],bootSector[0x2E],bootSector[0x2F]};
						return toLilEndian(aux,4);
					}

					unsigned int getSectorClusterN(unsigned int n,bootSector boot)
					{
						unsigned int addrs = (n- boot.rootCluster)*boot.sectorPerCluster+ boot.reservedSectors+ (boot.fatCant*boot.fatSize);

						return addrs;
					}
		bootSector getBootSector(char disk)
		{
			bootSector boot;
			char *map;

			map = mmap(0,1,PROT_READ ,MAP_PRIVATE, disk, 0);
			boot.reservedSectors = getReservedSectors(map);
			boot.fatSize = getFatSize(map);
			boot.fatCant = getNumberOfFat(map);
			boot.sectorPerCluster = getSectorPerCluster(map);
			boot.rootCluster = getRootCluster(map);

			return boot;
		}

		 int *getFreeClusters(char disk)
		{
			 int *map;
			 unsigned int *free;
						int i;

						map = mmap(0,1,PROT_READ ,MAP_PRIVATE, disk, 0x4000);

						for(i = 0; i < 1024; i++){
							if(map[i] == 0){
								printf("%d: %x\n",i, map[i]);
								agregar(free,map[i]);
							}

						}



		}


#endif /* UTILS_H_ */
